/*

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
   USA. 
*/
#include "string.h"
#include "libc.h"

/* For an optimized version, see BSD sources ;) */
void *memcpy(void *dst0, const void *src0, register unsigned int size)
{
  char *dst;
  const char *src;
  for (dst = (char*)dst0, src = (const char*)src0 ;
       size > 0 ;
       dst++, src++, size--)
    *dst = *src;
  return dst0;
}

/* ditto */
void *memset(void *dst0, register int c, register unsigned int length)
{
  char *dst;
  for (dst = (char*) dst0 ;
       length > 0 ;
       dst++, length --)
    *dst = (char)c;
  return dst0;
}

int memcmp(const void *s1, const void *s2, size_t len)
{
  const unsigned char *c1, *c2;
  unsigned int i;
 
  for (i = 0, c1 = s1, c2 = s2; i < len; i++, c1++, c2++)
    {
      if(*c1 != *c2)
        return *c1 - *c2;
    }
 
  return 0;
}


unsigned int strlen(register const char *str)
{
  unsigned int retval = 0;
  
  while (*str++)
    retval++;
  
  return retval;
}


unsigned int strnlen(const char * s, size_t count)
{
  const char *sc;
  
  for (sc = s; count-- && *sc != '\0'; ++sc)
    /* nothing */continue;

  return sc - s;
}


char *strzcpy(register char *dst, register const char *src, register int len)
{
  int i;

  if (len <= 0)
    return dst;
  
  for (i = 0; i < len; i++)
    {
      dst[i] = src[i];
      if(src[i] == '\0')
        return dst;
    }
  
  dst[len-1] = '\0'; 
  return dst;
}


char *strzcat (char *dest, const char *src, size_t n)
{
  char *res = dest;
  
  for ( ; *dest ; dest++);
  
  for ( ; *src ; src++, dest++) {
    *dest = *src;
    n--;
    if (n <= 0)
      break;
  }

  *dest = '\0';
  return res;
}


char *strndup(const char *s, size_t n)
{
  char * result;
  n = strnlen(s, n);
  result = malloc(n+1);
  if (! result)
    return NULL;

  strzcpy(result, s, n+1);
  return result;
}


char *strdup(const char *s)
{
  char * result;
  size_t n = strlen(s);

  result = malloc(n+1);
  if (! result)
    return NULL;

  strzcpy(result, s, n+1);
  return result;
}


int strcmp(register const char *s1, register const char *s2)
{
  while (*s1 == *s2++)
    if (*s1++ == 0)
      return (0);
  
  return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
}


int strncmp(register const char *s1, register const char *s2, register int len)
{
  char c1 = '\0', c2 = '\0';
  
  while (len > 0)
    {
      c1 = (unsigned char) *s1++;
      c2 = (unsigned char) *s2++;
      if (c1 == '\0' || c1 != c2)
        return c1 - c2;
      len--;
    }
  
  return c1 - c2;
}


long long int strtoll(const char *nptr, char **endptr, int base)
{
  long long int result;

#define RETURN(res) ({ if (endptr) *endptr = (char*)nptr; return res; })

  if (base > 36)
    {
      RETURN(0);
    }

  /* Skip leading  spaces */
  for ( ; *nptr != '\0' && isspace(*nptr) ; nptr++)
    continue;

  if (nptr[0] == '0')
    {
      if (nptr[1] == 'x')
	{
	  base = 16;
	  nptr += 2;
	}
      else
	{
	  base = 8;
	  nptr ++;
	}
    }

  result = 0;
  for ( ; *nptr != '\0' ; nptr ++)
    {
      int digit;
      if (*nptr >= '0' && *nptr <=  '9')
	digit = *nptr - '0';
      else if (*nptr >= 'a' && *nptr <=  'z')
	digit = 10 + *nptr - 'a';
      else if (*nptr >= 'A' && *nptr <=  'Z')
	digit = 10 + *nptr - 'A';
      else
	RETURN(result);
      if (digit >= base)
	{
	  RETURN(result);
	}
      result *= base;
      result += digit;
    }

  RETURN(result);
}

long int strtol(const char *nptr, char **endptr, int base)
{
  return strtoll(nptr, endptr, base);
}

long long atoll(const char *nptr)
{
  return strtoll(nptr, NULL, 10);
}

long atol(const char *nptr)
{
  return strtol(nptr, NULL, 10);
}
